<?php
/**
 * This file is part of Hyperf Mall.
 *
 * @link     https://gitee.com/scwlkj/hyperf_mall
 * @contact  hyperf_mall@163.com
 */

namespace App\Repository;


use App\Constants\Goods;
use App\Exception\BaseException;
use App\Model\GoodsModel;
use App\Utils\DB;
use App\Utils\Log;
use Hyperf\Di\Annotation\Inject;
use PHPUnit\Exception;


class GoodsRepository extends BaseRepository
{
    /**
     * @Inject
     * @var GoodsModel
     */
    protected $model;

    /**
     * Notes: 商品初始项
     * @return array
     */
    public function initData() : array
    {
        $return = [];

        $re = BrandRepository::getInstance()->getPageRows(['status'=>Goods::STATUS_UP],['name','id'],1,200);
        $return['brand'] = $re['data'];
        $return['cate'] = GoodsCategoryRepository::getInstance()->getTree();
        $tag = TagRepository::getInstance()->getPageRows(['status'=>Goods::STATUS_UP],['name','id'],1,200);
        $return['tags'] = $tag['data'];
        $return['attr'] = BaseAttributeRepository::getInstance()->getAllAttr();

        return $return;
    }

    /**
     * Notes: 添加/编辑
     * Author: Bruce.z
     * DateTime: 2022/6/6 17:32
     * @param $data
     * @param int $goods_id
     * @return bool
     * @throws BaseException
     */
    public function baseCreate($data, int $goods_id = 0): bool
    {
        $base = $data['base'];
        $images = is_array($base['images']) ? array_column($base['images'], 'url') : [];

        $goods = [
            'name'=>            $base['name'],
            'share_intro'=>     $base['share_intro']??'',
            'intro'=>           $base['intro'],
            'brand_id'=>        $base['brand_id']??0,
            'type_id'=>         $base['attr_id']??0,
            'category_id'=>     $base['category_id']?end($base['category_id']):0,
            'img'=>             !empty($images) ? current($images) : '',
            'images'=>          serialize($images),
            'unit'=>            $base['unit'],
            'bn'=>              $base['bn'],
            'sort'=>            $base['sort']??0,
            'tags'=>            (isset($base['tag_value']) && is_array($base['tag_value']))?implode(',', $base['tag_value']) : '',
            'is_postage'=>      $base['is_postage']?1:0,
            'spec_type'=>       ($base['spec_type'] && $base['spec_type'] != 'false')?1:0,
            'stock'=>           $base['stock']??0,
            'stock_warning'=>   $base['stock_warning']??0,
            'cost_price'=>      $base['cost_price']??0,
            'retail_price'=>    $base['retail_price']??0,
            'market_price'=>    $base['market_price']??0,
            'shelve_time'=>     time(),
        ];

        $detail = [
            'video'=>   $base['video'] ?? '',
            'details'=> $base['details'] ?? '',
        ];
        DB::beginTransaction();
        try{
            if($goods_id == 0){
                $goods_model = $this->baseAdd($goods);
                $goods_id = $goods_model['id'];
            }else{
                $this->updateByConditions(['id'=>$goods_id], $goods);
            }

            $this->addAttr($goods_id, $data['attr'] ?? []); // 添加属性
            $this->addProduct($goods_id, $data['spec'] ?? [], $data['specList']);// 添加规格/sku货品
            $this->addGoodsDetail($goods_id, $detail);// 添加详情

            DB::commit();
        }catch (Exception $exception){
            DB::rollBack();
            throw new BaseException(BaseException::BASE_ERROR, $exception->getMessage());
        }

        return true;
    }

    /**
     * Notes: 添加/编辑 属性
     * Author: Bruce.z
     * DateTime: 2022/6/6 17:29
     * @param int $goods_id
     * @param array $data
     * @throws \Exception
     */
    protected function addAttr(int $goods_id, array $data)
    {
        if(!count($data)) return ;
        $attr_value = [];
        array_map(function ($val) use ($goods_id, &$attr_value){
            $value = $val['value'];
            if($val['type'] == Goods::ATTR_TYPE_RADIO) $value = $val['check'];
            elseif ($val['type'] == Goods::ATTR_TYPE_CHECKBOX) {
                $value = count($val['select']) ? implode(',', $val['select']) : '';
            }
            $attr_value[] = [
                'goods_id'=>                    $goods_id,
                'base_attribute_value_id'=>     $val['id'],
                'title'=>                       $val['title'],
                'value'=>                       $value,
                'sort'=>                        $val['sort']??0,
                //'show_type'=>                   $val['show_type'],
                'saas_id'=>                     get_saas_id(),
                'create_time'=>                 time(),
                'update_time'=>                 time(),
            ];
        }, $data);

        GoodsAttributeValueRepository::getInstance()->_searchFactor(['goods_id'=>$goods_id])->delete();
        GoodsAttributeValueRepository::getInstance()->batchAdd($attr_value);
    }

    /**
     * Notes: 添加拆分
     * Author: Bruce.z
     * DateTime: 2022/1/19 18:09
     * @param int $goods_id
     * @param array $data
     * @param array $spec_ist
     */
    protected function addProduct(int $goods_id, array $data, array $spec_ist)
    {
        if(!count($data)) return ;

        $spec_value_ids = array_column($data, '_id');
        $value_ids = [];
        array_map(function ($val) use (&$value_ids){
            $value_ids = array_unique(array_merge($value_ids, explode('-', $val)));
        }, $spec_value_ids);
        $rows = BaseSpecValueRepository::getInstance()->getRows(['id'=>$value_ids]);
        $spec_ids = array_column($rows, 'spec_id');
        $spec_rows = BaseSpecRepository::getInstance()->getRows(['id'=>$spec_ids]);

        $goods_spec = [];
        $goods_spec_values = [];
        $product = [];
        $spec_ist = array_column($spec_ist, null, 'id');

        array_map(function ($val) use (&$goods_spec, $goods_id){
            $goods_spec[] = [
                'goods_id'=>        $goods_id,
                'base_spec_id'=>    $val['id'],
                'title'=>           $val['title'],
                'sort'=>            $val['sort'],
                'show_type'=>       $val['show_type'],
                'saas_id'=>         get_saas_id(),
                'create_time'=>     time(),
                'update_time'=>     time(),
            ];
        }, $spec_rows);

        array_map(function ($val) use (&$goods_spec_values, $goods_id,$spec_ist){
            $_data = $spec_ist[$val['spec_id']]['spec_value'] ?? [];
            $_data_value = count($_data) ? array_column($_data, null, 'id') : [];
            $goods_spec_values[] = [
                'goods_id'=>            $goods_id,
                'base_spec_id'=>        $val['spec_id'],
                'base_spec_value_id'=>  $val['id'],
                'title'=>               $val['title'],
                'sort'=>                $val['sort'],
                'data'=>                $_data_value[$val['id']]['data'] ?? '',
                'saas_id'=>             get_saas_id(),
                'create_time'=>         time(),
                'update_time'=>         time(),
            ];
        }, $rows);

        array_map(function ($val) use (&$product, $goods_id){
            $product[] = [
                'pbn'=>                 $val['pbn'],
                'name'=>                '',
                'weight'=>              $val['weight'],
                'retail_price'=>        $val['retail_price'],
                'cost_price'=>          $val['cost_price'],
                'market_price'=>        $val['market_price'],
                'img'=>                 $val['img']??'',
                'barcode'=>             $val['barcode']??'',
                'is_up'=>               $val['status']??1,
                'stock'=>               $val['stock']??0,
                'spec_name'=>           $val['_name']??'',
                'spec_ids'=>            $val['_id']??'',
                'initial_sales'=>       $val['initial_sales']??0,
                'goods_id'=>            $goods_id,
                'saas_id'=>             get_saas_id(),
                'create_time'=>         time(),
                'update_time'=>         time(),
            ];
        }, $data);

        // 多规格下 商品价格信息取第一个属性 商品总库存为规格库存叠加

        $this->updateByConditions(['id'=>$goods_id],
            [
                'retail_price'=>$product[0]['retail_price'],
                'cost_price'=>$product[0]['cost_price'],
                'market_price'=>$product[0]['market_price'],
                'stock_warning'=>$product[0]['stock_warning'],
                'default_product_id'=>$product[0]['id'],
                'stock'=>array_sum(array_column($product, 'stock')),
                'sales_volume'=>array_sum(array_column($product, 'sales_volume')),
            ]);

        GoodsSpecValueRepository::getInstance()->_searchFactor(['goods_id'=>$goods_id])->delete();
        GoodsSpecRepository::getInstance()->_searchFactor(['goods_id'=>$goods_id])->delete();
        ProductRepository::getInstance()->_searchFactor(['goods_id'=>$goods_id])->delete();

        GoodsSpecValueRepository::getInstance()->batchAdd($goods_spec_values);
        GoodsSpecRepository::getInstance()->batchAdd($goods_spec);
        ProductRepository::getInstance()->batchAdd($product);
    }

    /**
     * Notes: 商品详情
     * Author: Bruce.z
     * DateTime: 2022/1/19 18:13
     * @param int $goods_id
     * @param $data
     */
    protected function addGoodsDetail(int $goods_id, $data){
        $detail = [
            'goods_id'=>        $goods_id,
            'details'=>         $data['details'],
            'video'=>           $data['video'] ?? '',
        ];

        $re = GoodsDetailRepository::getInstance()->getOne(['goods_id'=>$goods_id]);
        if(count($re)) GoodsDetailRepository::getInstance()->updateByConditions(['goods_id'=>$goods_id], $data);
        else GoodsDetailRepository::getInstance()->baseAdd($detail);
    }

    /**
     * Notes: 获取详情
     * Author: Bruce.z
     * DateTime: 2022/1/25 17:48
     * @param int $goods_id
     * @return array
     */
    public function detail(int $goods_id) : array
    {
        $info = $this->getOne(['id'=>$goods_id]);
        $detail = GoodsDetailRepository::getInstance()->getOne(['goods_id'=>$goods_id]);

        $product = ProductRepository::getInstance()->getRows(['goods_id'=>$goods_id]);
        $goods_spec = GoodsSpecRepository::getInstance()->getRows(['goods_id'=>$goods_id]);
        $goods_spec_val = GoodsSpecValueRepository::getInstance()->getRows(['goods_id'=>$goods_id]);
        $goods_attr_val = GoodsAttributeValueRepository::getInstance()->getRows(['goods_id'=>$goods_id],['id','base_attribute_value_id','value','title']);

        $info['images_copy'] = (array) unserialize($info['images']);
        $info['images'] = (array) unserialize($info['images']);
        $info['cate'] = GoodsCategoryRepository::getInstance()->getParentID($info['category_id']);
        return [
            'base'=>$info,
            'detail'=>$detail,
            'product'=>$product,
            'goods_spec'=>$goods_spec,
            'goods_spec_val'=>$goods_spec_val,
            'goods_attr_val'=>$goods_attr_val,
        ];
    }


    /**
     * Notes: 更新
     * Author: Bruce.z
     * DateTime: 2022/6/6 17:31
     * @param $id
     * @param $data
     * @return bool
     * @throws BaseException
     */
    public function baseUpdate($id, $data){
        return $this->baseCreate($data, $id);
    }


    /**
     * Notes: 获取app 首页推荐商品
     * Author: Bruce.z
     * DateTime: 2022/6/13 18:02
     * @return array
     */
    public function appIndexList():array
    {
        $condition['is_up'] = Goods::STATUS_UP;
        $this->_searchFactor($condition)->orderByDesc('sort')->offset(0)->limit(6)->get(['id','img','name','retail_price'])->toArray();

        return [
            [
                'name'=>'平台推荐',
                'info'=>'你好 hypref mall',
                'goods'=>$this->_searchFactor($condition)->orderByDesc('sort')->offset(0)->limit(6)->get(['id','img','name','retail_price'])->toArray()
            ],
            [
                'name'=>'热销商品',
                'info'=>'你好 hypref mall',
                'goods'=>$this->_searchFactor($condition)->orderByDesc('sales_volume')->offset(0)->limit(6)->get(['id','img','name','retail_price'])->toArray()
            ],
            [
                'name'=>'最新上架',
                'info'=>'你好 hypref mall',
                'goods'=>$this->_searchFactor($condition)->orderByDesc('id')->offset(0)->limit(6)->get(['id','img','name','retail_price'])->toArray()
            ]
        ];
    }

    /**
     * Notes: c端 商品列表
     * Author: Bruce.z
     * DateTime: 2022/6/14 15:47
     * @param array $param
     * @return array
     */
    public function appList(array $param):array
    {
        $condition['is_up'] = Goods::STATUS_UP;
        $offset = max(($param['page']-1),0)*$param['size'];

        if(isset($param['name']) && !empty(trim($param['name']))){
            array_push($condition, ['name','like','%'.trim($param['name']).'%']);
        }

        if(isset($param['category_id']) && !empty(trim($param['category_id']))){
            array_push($condition, ['category_id',intval($param['category_id'])]);
        }

        $sort_field = 'sort';
        $sort_way = 'desc';
        $param['sort'] = $param['sort'] ?? 0;

        switch ($param['sort']){
            case Goods::SORT_SALES:
                $sort_field = 'sales_volume';
                break;
            case Goods::SORT_PRICE_DESC:
                $sort_field = 'retail_price';
                break;
            case Goods::SORT_PRICE_ASC:
                $sort_field = 'retail_price';
                $sort_way = 'asc';
                break;
            default:
                break;
        }

        $count = $this->_searchFactor($condition)->count();

        $goods =  $this->_searchFactor($condition)
            ->orderBy($sort_field, $sort_way)
            ->offset($offset)
            ->limit($param['size'])
            ->get(['id','img','name','retail_price','market_price','sales_volume','preset_num'])
            ->toArray();

        $param['top_id'] = $param['top_id'] ?? 0;
        $category = GoodsCategoryRepository::getInstance()->getNextCategory($param['top_id']);

        return ['total'=>$count, 'goods'=>$goods, 'category'=>$category];
    }

    /**
     * Notes: c端详情页
     * Author: Bruce.z
     * DateTime: 2022/6/14 17:21
     * @param int $id
     * @param int $member_id
     * @return array
     */
    public function appDetail(int $id, int $member_id):array
    {
        $data['info'] = $this->getOne(['id'=>$id],['name','stock','share_intro','intro','images','status','is_up','preset_num','retail_price','market_price','tags','sales_volume','img','spec_type']);
        $data['detail'] = GoodsDetailRepository::getInstance()->getOne(['goods_id'=>$id],['goods_id','details']);
        $data['product'] = ProductRepository::getInstance()->getRows(['goods_id'=>$id],['id','goods_id','name','weight','retail_price','market_price','stock','img','spec_name','initial_sales','spec_ids']);

        $data['goods_spec'] = GoodsSpecRepository::getInstance()->getRows(['goods_id'=>$id],['id','title','base_spec_id']);
        $data['goods_spec_val'] = GoodsSpecValueRepository::getInstance()->getRows(['goods_id'=>$id],['id','title','base_spec_id','base_spec_value_id']);
        $data['goods_attr_val'] = GoodsAttributeValueRepository::getInstance()->getRows(['goods_id'=>$id],['id','base_attribute_value_id','value','title']);

        $data['service'] = [];
        if(!empty($data['info']['tags'])){
            $_condition['id'] = explode(',', $data['info']['tags']);
            $_condition['status'] = Goods::STATUS_UP;
            $data['service'] = TagRepository::getInstance()->getRows($_condition, ['name']);
        }
        $data['is_collect'] = 0;
        if($member_id){
            $re = GoodsCollectRepository::getInstance()->getOne(['member_id'=>$member_id,'goods_id'=>$id],['id']);
            $data['is_collect'] = count($re) ? 1 : 0;
        }


        $data['info']['images'] = (array) unserialize($data['info']['images']);

        return $data;
    }

    /**
     * Notes: 返回货品对应库存
     * Author: Bruce.z
     * DateTime: 2022/6/27 16:42
     * @param array $data
     * @return int
     */
    public function getProductStock(array $data):int
    {
        if($data['product_id']){
            $re =  ProductRepository::getInstance()->getOne(['id'=>$data['product_id']], ['stock']);
        }else{
            $re = $this->getOne(['id'=>$data['goods_id']], ['stock']);
        }

        return $re['stock'] ?? 0;
    }

    /**
     * Notes: 获取商品上下架状态与价格
     * Author: Bruce.z
     * DateTime: 2022/7/1 10:46
     * @param array $ids
     * @return array
     */
    public function getStatusIds(array $ids):array
    {
        $res = $this->getRows(['id'=>$ids],['id','is_up','retail_price','stock','name','img']);
        return array_column($res, null,'id');
    }
}
